파라미터 연결하기

✒️ 2025-05-28 13:02 내용 수정


사용하는 Annotation

1. @RequestParam

(@RequestParam(name="name", required=true, defaultValue="0") dataType name)
옵션 설명
name 이름 가져올 파라미터의 이름
required true/false 파라미터 필수 여부. true라면 반드시 값이 넘어와야 하며, 값이 넘어오지 않으면 400 error 발생
defaultValue 기본값 넘어온 값이 없을 때 기본값 설정
@Controller
public class RequestParamTest {
	public static final String VIEW_PATH = "/WEB-INF/views/";
	
	@RequestMapping("requestParam")
	public String main(HttpServletRequest request) {
		String year = request.getParameter("year");
		System.out.printf("[%s]year=[%s]%n", new Date(), year);
		return VIEW_PATH + "date.jsp";
	}
	
	@RequestMapping("requestParam2")
	//public String main2(@RequestParam(name="year", required=false) String year) {
		public String main2(String year) { // 위와 동일
		// localhost/requestParam --> year=null : 400 error
		// localhost/requestParam?year --> year=""
		System.out.printf("[%s]year=[%s]%n", new Date(), year);
		return VIEW_PATH + "date.jsp";
	}
	
	@RequestMapping("requestParam3")
	public String main3(@RequestParam String year) {
		System.out.printf("[%s]year=[%s]%n", new Date(), year);
		return VIEW_PATH + "date.jsp";
	}
	
	@RequestMapping("requestParam4")
	public String main4(@RequestParam(required=false, defaultValue="1") String year) {
		// localhost/requestParam --> year=1
		// localhost/requestParam?year --> year=1
		System.out.printf("[%s]year=[%s]%n", new Date(), year);
		return VIEW_PATH + "date.jsp";
	}
	
	// ===============================================
	// year가 int로 넘어올 때
	@RequestMapping("requestParam5")
	public String main5(int year) {
		// localhost/requestParam --> year=null : 500 error
		// localhost/requestParam?year --> year="" : 400 error
		System.out.printf("[%s]year=[%s]%n", new Date(), year);
		return VIEW_PATH + "date.jsp";
	}
}

2. @ModelAttribute

public String test(@ModelAttribute("dto") PersonDTO dto) {}
public @ModelAttribute("name") int test() {}

실습

0. 프로젝트 설정

1. DTO 클래스 생성

package dto;

import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class PersonDTO {
	private String name, tel;
	private int age;
	
	@Override
	public String toString() {
		return "PersonDTO[name="+name+", tel="+tel+", age="+age+"]";
	}
}

2. 데이터를 받을 jsp 생성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
	<script>
		function send1(f) {
			let name = f.name.value;
			let tel = f.tel.value;
			let age = f.age.value;
			
			if(name==''){
				alert('이름을 입력해주세요');
				return;
			}
			if(tel==''){
				alert('전화번호를 입력해주세요');
				return;
			}
			if(age==''){
				alert('나이를 입력해주세요');
				return;
			}
			
			f.action = "insert1";
			f.method = "post";
			f.submit();
		}
		
		function send2(f) {
			let name = f.name.value;
			let tel = f.tel.value;
			let age = f.age.value;
			
			if(name==''){
				alert('이름을 입력해주세요');
				return;
			}
			if(tel==''){
				alert('전화번호를 입력해주세요');
				return;
			}
			if(age==''){
				alert('나이를 입력해주세요');
				return;
			}
			
			f.action = "insert2";
			f.method = "post";
			f.submit();
		}
	</script>
</head>
<body>
	<form>
		<table border="1" align="center">
		<caption>:::개인정보 입력:::</caption>
		<tr>
			<th>이름</th>
			<td><input name="name"></td>
		</tr>
		<tr>
			<th>전화번호</th>
			<td><input name="tel"></td>
		</tr>
		<tr>
			<th>나이</th>
			<td><input name="age"></td>
		</tr>
		<tr>
			<td colspan="2" align="center">
			<input type="button" value="낱개로 받기" onclick="send1(this.form)">
			<input type="button" value="객체로 받기" onclick="send2(this.form)">
			</td>
		</tr>
		</table>
	</form>
</body>
</html>

3. 파라미터를 받아 바인딩과 포워딩을 할 Controller

package com.nogroup.mvc;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import dto.PersonDTO;
import util.MyPath.HomeClass;

@Controller
public class ParamController {
	
	@RequestMapping(value= {"/", "insert_form"})
	public String inset_form() {
		return HomeClass.VIEW_PATH + "insert_form.jsp"; 
	}
	
	// insert1?name=이름&tel=전화번호&age=40
	@RequestMapping("insert1")
	public String insert1(@RequestParam String name,
							@RequestParam String tel,
							@RequestParam int age,
							Model model) {
		PersonDTO dto = new PersonDTO();
		dto.setName(name);
		dto.setTel(tel);
		dto.setAge(age);
		
		model.addAttribute("dto", dto);
		return HomeClass.VIEW_PATH + "insert_result.jsp";
	}
		
	@RequestMapping("insert2")
	public String insert2(@ModelAttribute("dto") PersonDTO dto) {
		getYear(dto);
		return HomeClass.VIEW_PATH + "insert_result.jsp";
	}
	
	// 메소드를 실행하고 난 결과를 annotation에 붙은 단어를 key값으로 model에 바인딩
	private @ModelAttribute("year") int getYear(PersonDTO dto) {
		return 2024-dto.getAge();
	}
}

4. 결과를 확인할 jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<p>이름 : ${dto.name }</p>
	<p>나이 : ${dto.age }</p>
	<p>전화번호 : ${dto.tel }</p>
	<p>년도 : ${year} <p>
	
	<input type="button" value="돌아가기" onclick="location.href='insert_form'">
</body>
</html>

param 1.png


데이터를 객체에 묶은 방법

package com.nogroup.mvc;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import org.springframework.util.StringUtils;

public class SetterCall {
	public static void main(String[] args) throws Exception {
		
		// 요청한 값이 HashMap에 담겨있다 하면
		Map<String, String> map = new HashMap<String, String>();
		map.put("name", "홍길동");
		map.put("tel", "010-111-1111");
		map.put("age", "10");
		
		Class<?> type = Class.forName("dto.PersonDTO");
		
		// PersonDTO 인스턴스를 생성하고, map의 값으로 초기화
		Object obj = dataBind(map,type);
		System.out.println("obj="+obj);
	}

	private static Object dataBind(Map<String, String> map, Class<?> clazz) throws Exception {
		
		// 1. PersonDTO 인스턴스 생성
		Object obj = clazz.getDeclaredConstructor().newInstance(new Object[0]);
		
		// 2. PersonDTO 인스턴스의 setter를 호출해서 map의 값으로 PersonDTO를 초기화
		// 2-1. PersonDTO의 모든 필드를 돌면서 map에 있는지 확인
		// 2-2. 찾으면 찾은 값을 setter로 객체에 저장
		Field[] ivArr = clazz.getDeclaredFields();
		
		for(int	i = 0; i < ivArr.length; i++) {
			String name = ivArr[i].getName();
			Class<?> type = ivArr[i].getType();
			
			// map에 같은 이름의 key가 있으면 가져와서 setter 호출
			Object value = map.get(name); // 못 찾으면 value값은 null
			Method method = null;
			
			try {
				// map에 iv와 일치하는 키가 있을 때만 setter 호출
				if (value==null) continue;
				
				method = clazz.getDeclaredMethod(getSetterName(name), type); // setter 정보 가져오기
				System.out.println(method);
				method.invoke(obj, convertTo(value, type)); //obj의 setter호출
			} catch (Exception e) {
				// TODO: handle exception
			}
		}
		System.out.println(Arrays.toString(ivArr));
		return obj;
	}
	
	private static Object convertTo(Object value, Class<?> type) {
		// value의 타입과 type의 타입이 같으면 그대로 반환
		if(value==null||type==null||type.isInstance(value)) {
			return value;
		}
		
		// value의 타입과 type의 타입이 다르면 변환해서 반환
		if(String.class.isInstance(value) && type==int.class) {
			return Integer.valueOf(""+value);
		}
		
		return value;
	}
	
	// iv의 이름으로 setter의 이름을 만들어서 반환하는 메소드("name" --> "setName")
	private static String getSetterName(String name) {
		return "set"+StringUtils.capitalize(name);
	}
}